﻿using System.Collections.Generic;
using System.ComponentModel;

namespace System
{
    public static class DomainCopier
    {
        public static void CopyCollection<T>(this IEnumerable<T> from, ICollection<T> to)
        {
            if (from == null || to == null || to.IsReadOnly)
            {
                return;
            }
            to.Clear();
            foreach (T current in from)
            {
                to.Add(current);
            }
        }

        public static void CopyCollection<TSource, TDestination>(this IEnumerable<TSource> from, ICollection<TDestination> to) where TDestination : new()
        {
            if (from == null || to == null || to.IsReadOnly)
            {
                return;
            }
            to.Clear();
            foreach (TSource current in from)
            {
                var itemTo = new TDestination();
                current.CopyDomain(itemTo);
                to.Add(itemTo);
            }
        }

        public static void CopyDomain(this object from, object to)
        {
            if (from == null || to == null)
            {
                return;
            }
            PropertyDescriptorCollection properties = TypeDescriptor.GetProperties(from);
            PropertyDescriptorCollection properties2 = TypeDescriptor.GetProperties(to);
            foreach (PropertyDescriptor propertyDescriptor in properties)
            {
                PropertyDescriptor propertyDescriptor2 = properties2.Find(propertyDescriptor.Name, true);
                if (propertyDescriptor2 != null && !propertyDescriptor2.IsReadOnly)
                {
                    bool flag = propertyDescriptor2.PropertyType.IsAssignableFrom(propertyDescriptor.PropertyType);
                    bool flag2 = !flag && Nullable.GetUnderlyingType(propertyDescriptor.PropertyType) == propertyDescriptor2.PropertyType;
                    if (flag || flag2)
                    {
                        object value = propertyDescriptor.GetValue(from);
                        if (flag || (value != null))
                        {
                            propertyDescriptor2.SetValue(to, value);
                        }
                    }
                }
            }
        }
    }
}